package xyz.penghaonan.p2plib.job.base;

import com.penghaonan.appframework.utils.WeakObservableList;

import java.util.LinkedList;
import java.util.List;

import xyz.penghaonan.p2plib.job.JobUtils;

abstract public class BaseOperation<T> implements Operation<T> {
    private final WeakObservableList<OperationListener> operationListenerList = new WeakObservableList<>();
    private Job job;
    private Result<T> result = Result.defaultResult();
    protected final int[] lock = new int[0];

    public BaseOperation() {
    }

    @Override
    public void addListener(OperationListener listener) {
        operationListenerList.addListener(listener);
    }

    @Override
    public void removeListener(OperationListener listener) {
        operationListenerList.removeListener(listener);
    }

    @Override
    final public void run(Job job) {
        this.job = job;
        JobUtils.postOnUIThread(new Runnable() {
            @Override
            public void run() {
                operationListenerList.iterate(new OperationListenerIterator() {
                    @Override
                    void onListenerIterator(OperationListener item) {
                        item.onOperationStart(BaseOperation.this);
                    }
                });
            }
        });

        doOperation();

        JobUtils.postOnUIThread(new Runnable() {
            @Override
            public void run() {
                operationListenerList.iterate(new OperationListenerIterator() {
                    @Override
                    void onListenerIterator(OperationListener item) {
                        item.onOperationFinish(BaseOperation.this, result);
                    }
                });
            }
        });
        onFinish(result);
    }

    @Override
    public abstract void doOperation();


    @Override
    public void onFinish(Result<T> result) {

    }

    protected void operationContinue() {
        synchronized (lock) {
            lock.notifyAll();
        }
    }

    protected void operationWait() {
        operationWait(3000);
    }

    protected void operationWait(long time) {
        try {
            synchronized (lock) {
                lock.wait(time);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    protected void notifyProgress(final float progress, final String msg) {
        JobUtils.postOnUIThread(new Runnable() {
            @Override
            public void run() {
                operationListenerList.iterate(new OperationListenerIterator() {
                    @Override
                    void onListenerIterator(OperationListener item) {
                        item.onOperationProgress(BaseOperation.this, progress, msg);
                    }
                });
            }
        });
    }

    protected void setResult(Result<T> result) {
        this.result = result;
    }

    public Result<T> getResult() {
        return result;
    }

    protected void log(String log) {
        JobUtils.log("opration:" + getClass().getSimpleName() + " " + log);
    }

    private abstract static class OperationListenerIterator extends WeakObservableList.OnIterator<OperationListener> {
        private final List<OperationListener> jobList = new LinkedList<>();

        @Override
        protected boolean onIterator(OperationListener item) {
            if (item instanceof OperationListenerForJob) {
                jobList.add(item);
            } else {
                onListenerIterator(item);
            }
            return false;
        }

        abstract void onListenerIterator(OperationListener item);

        @Override
        protected void onFinish() {
            super.onFinish();
            for (OperationListener item : jobList) {
                onListenerIterator(item);
            }
        }
    }
}
